home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Programmer Disk
/
The Programmer Disk (Microforum).iso
/
xpro
/
bc
/
pro23
/
ackutil.c
< prev
next >
Wrap
Text File
|
1993-08-22
|
10KB
|
415 lines
/******************* ( Animation Construction Kit 3D ) ***********************/
/* Utility Routines */
/* CopyRight (c) 1993 Author: Lary Myers */
/*****************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <mem.h>
#include <alloc.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <sys\stat.h>
#include "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
#include "xmslib.h"
#define XMS_LOWVALUE 0x0280
#define XMS_HIVALUE 0xA000
/****************************************************************************
** Return the square root of a long value **
****************************************************************************/
long long_sqrt(long v)
{
int i;
unsigned long result,tmp;
unsigned long low,high;
if (v <= 1L) return((unsigned)v);
low = v;
high = 0L;
result = 0;
for (i = 0; i < 16; i++)
{
result += result;
high = (high << 2) | ((low >>30) & 0x3);
low <<= 2;
tmp = result + result + 1;
if (high >= tmp)
{
result++;
high -= tmp;
}
}
if (v - (result * result) >= (result - 1))
result++;
return(result);
}
/****************************************************************************
** The application can use this routine to read in a 768 byte palette **
** file and immediately set it in the video. PalName is the name of the **
** palette file to load. **
** **
****************************************************************************/
int AckLoadAndSetPalette(char *PalName)
{
int handle,ErrCode;
char *buf;
buf = malloc(800);
if (buf == NULL)
return(ERR_NOMEMORY);
ErrCode = 0;
handle = open(PalName,O_RDWR|O_BINARY);
if (handle > 0)
{
read(handle,buf,768);
close(handle);
AckSetPalette(buf);
}
else
ErrCode = ERR_BADFILE;
free(buf);
return(ErrCode);
}
/****************************************************************************
** The application calls this routine to get the last object hit (from the **
** AckMovePOV() or AckMoveObjectPOV() routines. **
** **
****************************************************************************/
int AckGetObjectHit(void)
{
return(LastObjectHit);
}
/****************************************************************************
** The application calls this routine to get the last wall hit (from the **
** AckMovePOV() or AckMoveObjectPOV() routines. **
** **
****************************************************************************/
int AckGetWallHit(void)
{
return(LastMapPosn);
}
/****************************************************************************
** The application calls this routine to make an object invisible. The **
** object and object bitmaps are NOT deleted. Currently the active flag **
** is set to zero however, future versions may do more in the routine so **
** it would be a good idea for the application to call here instead of **
** setting the active flag to zero on its own. **
** **
****************************************************************************/
int AckDeleteObject(ACKENG *ae,int ObjIndex)
{
int MapPosn;
if (!ae->ObjList[ObjIndex].Active)
return(-1);
ae->ObjList[ObjIndex].Active = 0;
return(0);
}
/****************************************************************************
** The purpose of this routine is to replace an existing bitmap with a **
** new one. The old bitmap is freed and the new one is put into place in **
** the specified bitmap array. **
** **
** index is the number of the bitmap array to replace **
** Maps is the bitmap array **
** NewBitmap is a pointer to the new bitmap to use **
** **
****************************************************************************/
int AckSetNewBitmap(int index,UCHAR far **Maps,UCHAR far *NewBitmap)
{
int i;
UCHAR far *bPtr;
bPtr = Maps[index];
if (FP_SEG(bPtr) < XMS_HIVALUE && FP_SEG(bPtr) > XMS_LOWVALUE)
{
if (bPtr == NewBitmap)
return(0);
free(bPtr);
Maps[index] = NewBitmap;
return(0);
}
#if USE_XMS
XMSput((XMSHANDLE)bPtr,NewBitmap,BITMAP_SIZE);
for (i = 0; i < MAX_XARRAY; i++)
{
if (bPtr == (UCHAR far *)xArray[i].xHandle)
{
memmove(xArray[i].Bmp,NewBitmap,BITMAP_SIZE);
}
}
#endif
return(0);
}
/****************************************************************************
** This routine should be called for all wall and object bitmaps when using**
** XMS memory. It will copy the bitmap from XMS to a real memory array **
** buffer which is then passed back to the caller. It checks for a buffer **
** that has the smallest usage count (an empty one would have zero), to **
** copy the XMS memory into. XMS handles have been observed to have a seg **
** value of > A000H or < 100H (which hopefully will be true all the time!) **
****************************************************************************/
UCHAR far *AckGetBitmapPtr(int index,UCHAR far **Maps)
{
int i,min,Lasti;
UCHAR far *bPtr;
bPtr = Maps[index];
#if USE_XMS
if (FP_SEG(bPtr) < XMS_HIVALUE && FP_SEG(bPtr) > XMS_LOWVALUE)
return(bPtr);
min = 32000;
Lasti = -1;
for (i = 0; i < MAX_XARRAY; i++)
{
if (bPtr == (UCHAR far *)xArray[i].xHandle)
{
xArray[i].count++;
return(xArray[i].Bmp);
}
if (xArray[i].count < min)
{
min = xArray[i].count;
Lasti = i;
}
}
if (Lasti == -1)
{
XMSget(BitmapXferPtr,(XMSHANDLE)bPtr);
return(BitmapXferPtr);
}
XMSget(xArray[Lasti].Bmp,(XMSHANDLE)bPtr);
xArray[Lasti].count = 1;
xArray[Lasti].xHandle = (ULONG)bPtr;
return(xArray[Lasti].Bmp);
#else
return(bPtr);
#endif
}
#define LOCK_MAX 20
typedef struct {
XMSHANDLE xHandle;
UCHAR far *Bmp;
} LOCKLIST;
LOCKLIST LockTable[LOCK_MAX+1];
/****************************************************************************
** This routine loads an XMS bitmap into memory for use by the app. If the **
** bitmap is not in XMS then the bitmap pointer itself is returned. **
** **
****************************************************************************/
UCHAR far *AckLockPtr(UCHAR far *bPtr)
{
int i,uFlag;
UCHAR far *bmp;
#if USE_XMS
uFlag = 0;
if (FP_SEG(bPtr) < XMS_HIVALUE && FP_SEG(bPtr) > XMS_LOWVALUE)
return(bPtr);
bmp = malloc(BITMAP_SIZE);
if (bmp == NULL)
return(bmp);
XMSget(bmp,(XMSHANDLE)bPtr);
for (i = 0; i < LOCK_MAX; i++)
{
if (LockTable[i].Bmp == NULL)
{
LockTable[i].Bmp = bmp;
LockTable[i].xHandle = (XMSHANDLE)bPtr;
uFlag = 1;
break;
}
}
if (!uFlag)
{
LockTable[0].Bmp = bmp;
LockTable[0].xHandle = (XMSHANDLE)bPtr;
}
return(bmp);
#else
return(bPtr);
#endif
}
/****************************************************************************
** This routine frees up a previously locked pointer. If the pointer is **
** not in XMS then no action is taken. **
** **
****************************************************************************/
int AckUnlockPtr(UCHAR far *bPtr)
{
int i,j;
#if USE_XMS
for (i = 0; i < LOCK_MAX; i++)
{
if (LockTable[i].Bmp == bPtr)
{
XMSput(LockTable[i].xHandle,bPtr,BITMAP_SIZE);
for (j = 0; j < MAX_XARRAY; j++)
{
if (xArray[j].xHandle == LockTable[i].xHandle)
{
memmove(xArray[j].Bmp,bPtr,BITMAP_SIZE);
break;
}
}
free(LockTable[i].Bmp);
LockTable[i].Bmp = NULL;
return(0);
}
}
return(-1);
#else
return(0);
#endif
}
/****************************************************************************
** This routine creates a new bitmap buffer (in real or XMS memory) and **
** copies the supplied bitmap into it. The return pointer is either an **
** XMS handle or a pointer to the real memory. **
** **
****************************************************************************/
UCHAR far *AckCopyNewBitmap(UCHAR far *bPtr)
{
UCHAR far *bmp;
#if USE_XMS
XMSHANDLE xPtr;
if (UseXMS > 0)
{
xPtr = XMSalloc(BITMAP_SIZE);
if (xPtr != XMSHNULL)
{
if (FP_SEG(bPtr) > XMS_HIVALUE || FP_SEG(bPtr) < XMS_LOWVALUE)
XMSget(BitmapXferPtr,(XMSHANDLE)bPtr);
else
memmove(BitmapXferPtr,bPtr,BITMAP_SIZE);
XMSput(xPtr,BitmapXferPtr,BITMAP_SIZE);
return((UCHAR far *)xPtr);
}
else
{
bmp = malloc(BITMAP_SIZE);
if (bmp)
memmove(bmp,bPtr,BITMAP_SIZE);
return(bmp);
}
}
else
{
bmp = malloc(BITMAP_SIZE);
if (bmp)
memmove(bmp,bPtr,BITMAP_SIZE);
return(bmp);
}
#else
bmp = malloc(BITMAP_SIZE);
if (bmp)
memmove(bmp,bPtr,BITMAP_SIZE);
return(bmp);
#endif
}
/****************************************************************************
** This routine frees the memory used by a bitmap in either real or XMS **
** memory. **
** **
****************************************************************************/
int AckFreeBitmap(UCHAR far *Bmp)
{
int i;
#if USE_XMS
if (FP_SEG(Bmp) > XMS_HIVALUE || FP_SEG(Bmp) < XMS_LOWVALUE)
{
for (i = 0; i < MAX_XARRAY; i++)
{
if (xArray[i].xHandle == (XMSHANDLE)Bmp)
{
xArray[i].count = 0;
xArray[i].Bmp = XMSHNULL;
break;
}
}
XMSfree((XMSHANDLE)Bmp);
}
else
free(Bmp);
#else
free(Bmp);
#endif
return(0);
}